#include "TcpServer.h"


int TcpServer::acceptConnection(void* arg)
{
    //TcpServer* server = static_cast<TcpServer*>(arg);      //  C++
    TcpServer* server = (TcpServer*)arg;                     // C

    int cfd = accept(server->m_lfd, NULL, NULL);
    EventLoop* evLoop = server->m_threadPool->takeWorkerEventLoop();
    new TcpConnection(cfd, evLoop);
    return 0;
}

int TcpServer::acceptConnection_1()
{
    int cfd = accept(m_lfd, NULL, NULL);
    //cout << to_string(m_lfd) << ": 成功建立连接" << endl;
    EventLoop* evLoop = m_threadPool->takeWorkerEventLoop();

    //cout << "子线程: " << evLoop->getThreadID() << " 正在处理fd = "  << cfd << "事务" << endl;
    new TcpConnection(cfd, evLoop);

    return 0;
}

TcpServer::TcpServer(unsigned short port, int threadNum)
{
    m_port = port;
    m_mainLoop = new EventLoop;
    m_threadNum = threadNum;
    m_threadPool = new ThreadPool(m_mainLoop, threadNum);
    setListen();
}

void TcpServer::setListen()
{
    m_lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (m_lfd == -1)
    {
        perror("socket");
        return;
    }

    int opt = 1;
    int ret = setsockopt(m_lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    if (ret == -1)
    {
        perror("setsockopt");
        return;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(m_port);
    addr.sin_addr.s_addr = INADDR_ANY;
    ret = bind(m_lfd, (struct sockaddr*)&addr, sizeof(addr));
    if (ret == -1)
    {
        perror("bind");
        return;
    }

    ret = listen(m_lfd, 128);
    if (ret == -1)
    {
        perror("listen");
        return;
    }
}

void TcpServer::run()
{
    cout << "服务器启动..." << endl;

    m_threadPool->run();

    auto obj = bind(&TcpServer::acceptConnection_1, this);                                            // 可调用对象包装器方式
    Channel* channel = new Channel(m_lfd, FDEvent::ReadEvent, obj, nullptr, nullptr, this);
    //Channel* channel = new Channel(m_lfd, FDEvent::ReadEvent, acceptConnection, nullptr, nullptr, this);      // 静态函数方式

    cout << "mainLoop ID:" << m_mainLoop->getThreadID() << "    mainLoop Name: " << m_mainLoop->getThreadName() << endl;
    m_mainLoop->addTask(channel, ElemType::ADD);
    m_mainLoop->run();
}
